Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3장. HLS 구조와 Playlist(m3u8) 완전 해부

3.1 HLS의 3대 구성요소

2장에서 HLS는 영상을 조각으로 나눈다고 했다.

하지만 단순히 파일을 나누는 것만으로는 스트리밍이 동작하지 않는다.

플레이어는 다음을 알아야 한다.

  • 어떤 화질이 존재하는가
  • 어떤 순서로 재생해야 하는가
  • 다음에 무엇을 가져와야 하는가

이를 해결하는 구조가 HLS의 3대 구성요소다.

Playlist  +  Segment  +  Player
   ↓           ↓           ↓
 지도        실 영상      엔진

이 중 가장 중요한 것은 Playlist (m3u8)이다.

왜냐하면

플레이어는 실제 영상이 아니라 “playlist를 기준으로” 동작하기 때문이다


3.2 실제 HLS 디렉토리 구조

이론보다 실제 구조를 보는 것이 이해가 빠르다.

hls/
├── master.m3u8
├── 1080p/
│   ├── index.m3u8
│   ├── init.mp4         (fMP4 사용 시)
│   ├── seg100.ts
│   ├── seg101.ts
│   └── ...
├── 720p/
│   ├── index.m3u8
│   ├── seg100.ts
│   └── ...
├── 480p/
│   ├── index.m3u8
│   └── ...
├── audio/               (오디오 트랙 분리 시)
│   ├── ko/index.m3u8
│   └── en/index.m3u8
└── subtitle/
    ├── ko.m3u8
    └── en.m3u8

구조 특징

  • 화질별로 디렉토리가 분리됨
  • 동일한 시간 구간이 여러 화질로 존재
  • 오디오/자막은 별도 트랙으로 분리 가능

같은 번호의 segment는 같은 시간 구간을 의미한다.

1080p/seg100.ts
720p/seg100.ts
480p/seg100.ts

이 구조 덕분에:

플레이어는 같은 시점에서 화질을 자유롭게 변경할 수 있다 (ABR)


3.3 Master Playlist 완전 분석

Master Playlist는 “이 영상에 어떤 화질/트랙이 있는가“를 알려주는 카탈로그 역할을 한다.

(공식 명칭은 Multivariant Playlist다. 실무에서는 master playlist라고 더 많이 부른다.)


기본 예시

#EXTM3U
#EXT-X-VERSION:7

#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2"
1080p/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2"
720p/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.42c01e,mp4a.40.2"
480p/index.m3u8

플레이어는 이 파일을 보고 사용 가능한 화질 목록을 알게 된다.


3.3.1 EXT-X-STREAM-INF의 속성들

#EXT-X-STREAM-INF는 각 화질(variant)의 메타데이터를 담는다.

속성의미
BANDWIDTH최대 비트레이트 (bps), 필수
AVERAGE-BANDWIDTH평균 비트레이트
RESOLUTION해상도 (가로x세로)
CODECS코덱 식별자
FRAME-RATE프레임레이트
HDCP-LEVELDRM 출력 보호 레벨
VIDEO-RANGESDR / HDR10 / PQ
AUDIO연결된 오디오 GROUP-ID
SUBTITLES연결된 자막 GROUP-ID
CLOSED-CAPTIONS연결된 캡션 GROUP-ID

BANDWIDTH는 ABR이 화질을 고르는 핵심 기준이다.

플레이어는 현재 네트워크 속도와 BANDWIDTH를 비교해서 다음 화질을 선택한다.


3.3.2 EXT-X-MEDIA로 정의하는 대체 렌디션

영상에는 비디오 외에도 여러 오디오, 자막이 있을 수 있다.

이를 표현하는 태그가 #EXT-X-MEDIA다.

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",NAME="Korean",
  LANGUAGE="ko",DEFAULT=YES,AUTOSELECT=YES,
  URI="audio/ko/index.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",NAME="English",
  LANGUAGE="en",DEFAULT=NO,AUTOSELECT=YES,
  URI="audio/en/index.m3u8"

#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",NAME="Korean",
  LANGUAGE="ko",DEFAULT=YES,
  URI="subtitle/ko.m3u8"

주요 속성:

속성의미
TYPEAUDIO / VIDEO / SUBTITLES / CLOSED-CAPTIONS
GROUP-ID같은 그룹으로 묶이는 식별자
NAME사용자에게 보이는 이름
LANGUAGE언어 코드 (BCP 47)
DEFAULT기본 선택 여부
AUTOSELECT자동 선택 가능 여부
URI실제 playlist 경로

3.3.3 GROUP-ID로 묶이는 트랙 구조

GROUP-ID는 매우 중요한 개념이다.

비디오 variant는 자신과 연결될 오디오/자막 그룹을 명시한다.

#EXT-X-STREAM-INF:BANDWIDTH=5000000,
  RESOLUTION=1920x1080,
  AUDIO="aud1",       ← 오디오 그룹 연결
  SUBTITLES="sub1"    ← 자막 그룹 연결
1080p/index.m3u8

이 구조의 의미는 이렇다.

비디오는 한 줄, 오디오/자막은 별도 트랙으로 묶고, GROUP-ID로 연결한다.

이를 통해 같은 영상에 한국어/영어 오디오를 동시에 제공하거나 자막을 따로 토글할 수 있다.


3.3.4 EXT-X-I-FRAME-STREAM-INF

이 태그는 탐색/썸네일용 I-Frame 전용 playlist를 정의한다.

#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=200000,
  RESOLUTION=640x360,
  CODECS="avc1.42c01e",
  URI="iframe/index.m3u8"

왜 필요한가

영상에서 임의 위치로 점프할 때 플레이어는 keyframe(I-Frame)부터 디코딩해야 한다.

I-Frame만 모아둔 별도 playlist가 있으면:

  • 탐색이 빠르다
  • 썸네일 미리보기를 만들 수 있다
  • trick play (배속, 역재생)에 활용된다

3.3.5 EXT-X-INDEPENDENT-SEGMENTS

#EXT-X-INDEPENDENT-SEGMENTS

이 태그가 있으면 다음을 의미한다.

모든 segment는 자기 자신만으로 디코딩이 가능하다 (즉, 각 segment가 keyframe으로 시작한다)

이 보장이 있어야 ABR 전환이 어디서든 깨끗하게 일어난다.


3.4 Media Playlist의 주요 태그

Media Playlist는 실제 segment의 재생 순서를 정의하는 파일이다.

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:100
#EXT-X-MAP:URI="init.mp4"

#EXTINF:2.000,
seg100.m4s

#EXTINF:2.000,
seg101.m4s

#EXTINF:2.000,
seg102.m4s

3.4.1 EXT-X-VERSION

#EXT-X-VERSION:7

플레이어가 이 playlist를 해석하기 위해 필요한 최소 HLS 프로토콜 버전을 선언한다.

버전추가된 기능
3부동소수 EXTINF
4EXT-X-BYTERANGE
6EXT-X-MAP
7fMP4 (mp4 segment)
9EXT-X-PART (LL-HLS)

3.4.2 EXT-X-TARGETDURATION

#EXT-X-TARGETDURATION:2

segment 최대 길이 (초).

  • 짧을수록 지연 감소
  • 길수록 요청 횟수 감소

Latency vs 효율의 트레이드오프

플레이어는 이 값을 기준으로 playlist를 얼마나 자주 다시 가져올지를 결정한다.


3.4.3 EXT-X-MEDIA-SEQUENCE

#EXT-X-MEDIA-SEQUENCE:100

현재 playlist의 첫 segment 번호.

라이브 스트리밍에서는 시간이 지나면서 이 값이 증가한다.

T+0초    : MEDIA-SEQUENCE=100, segments [100,101,102]
T+2초    : MEDIA-SEQUENCE=101, segments [101,102,103]
T+4초    : MEDIA-SEQUENCE=102, segments [102,103,104]

플레이어는 이 번호로 현재 재생 위치를 추적한다.


3.4.4 EXTINF

#EXTINF:2.000,
seg100.m4s
  • 다음 segment의 재생 길이 (초)
  • 그 다음 줄에 segment URI

길이는 TARGETDURATION 이하여야 한다.


3.4.5 EXT-X-MAP (Initialization Segment)

#EXT-X-MAP:URI="init.mp4"

fMP4를 사용할 때 등장하는 태그.

init.mp4는 실제 영상 데이터를 담고 있지 않다.

대신:

  • 코덱 정보
  • 트랙 메타데이터
  • 디코더 초기화 데이터

가 들어있다.

플레이어는 init.mp4를 먼저 다운로드한 뒤 각 segment를 재생한다.

(TS 포맷은 init segment가 필요 없다. 각 TS segment에 PAT/PMT가 포함되어 있기 때문이다. 자세한 건 4.2절에서 다룬다.)


3.4.6 EXT-X-BYTERANGE

#EXTINF:2.000,
#EXT-X-BYTERANGE:1048576@0
big.mp4

#EXTINF:2.000,
#EXT-X-BYTERANGE:1048576@1048576
big.mp4

하나의 큰 파일을 바이트 범위로 잘라서 사용할 수 있다.

이렇게 하면:

  • 파일 수가 줄어든다
  • 서버 관리가 편해진다
  • HTTP Range 요청으로 부분만 가져온다

3.5 VOD와 Live의 구분

같은 m3u8 형식이지만 VODLive는 동작이 다르다.

이를 구분하는 태그들이 있다.


3.5.1 EXT-X-PLAYLIST-TYPE

#EXT-X-PLAYLIST-TYPE:VOD

값은 두 가지.

의미
VOD완성된 영상. playlist 변경 없음
EVENT추가만 가능 (라이브 녹화)

이 태그가 없으면 일반 라이브로 간주된다. (playlist가 sliding window로 갱신됨)


3.5.2 EXT-X-ENDLIST

#EXT-X-ENDLIST

더 이상 segment가 추가되지 않음을 의미한다.

  • VOD의 마지막
  • 종료된 라이브 (생방송 끝)

이 태그를 보면 플레이어는 playlist를 더 이상 다시 요청하지 않는다.


3.5.3 EXT-X-DISCONTINUITY

#EXTINF:2.000,
seg100.ts

#EXT-X-DISCONTINUITY
#EXTINF:2.000,
ad_001.ts

다음 segment가 이전 segment와 연속성이 끊긴다는 표시.

주로 다음 상황에서 사용된다.

  • 광고 삽입 (SSAI)
  • 코덱/해상도 변경
  • 타임스탬프 불연속

플레이어는 이 태그를 보면 디코더를 리셋한다.


3.6 플레이어 동작 흐름

플레이어는 다음 과정을 반복한다.

1. master.m3u8 요청
2. 화질/오디오/자막 선택
3. 각 트랙의 index.m3u8 요청
4. (필요시) init.mp4 요청
5. segment 다운로드
6. 디코딩 + 재생
7. playlist 재요청 (라이브의 경우)
8. 다음 segment 결정 → 5번으로 돌아감

핵심 특징:

플레이어는 playlist를 계속 다시 읽는다

이 polling 구조가 5장에서 다룰 지연의 근본 원인 중 하나다.


3.7 Live Streaming과 Sliding Window

라이브에서는 playlist가 계속 변경된다.


시점 T+0

#EXT-X-MEDIA-SEQUENCE:100
#EXTINF:2.0,
seg100.ts
#EXTINF:2.0,
seg101.ts
#EXTINF:2.0,
seg102.ts

시점 T+2초

#EXT-X-MEDIA-SEQUENCE:101
#EXTINF:2.0,
seg101.ts
#EXTINF:2.0,
seg102.ts
#EXTINF:2.0,
seg103.ts

특징

  • 오래된 segment는 목록에서 제거된다
  • 새로운 segment가 끝에 추가된다
  • 총 segment 개수는 일정하게 유지된다

이 구조를 Sliding Window라고 한다.

항상 최신 영상만 유지한다

뒤로 무한정 되감기는 불가능하다. (라이브 DVR 기능은 별도 설계가 필요하다)


3.8 HLS 구조의 본질

이제 전체를 정리하면 이렇다.

서버의 역할

  • playlist 제공
  • segment 제공
  • (필요시) init segment 제공

플레이어의 역할

  • playlist 분석
  • 다음 segment 계산
  • 직접 요청
  • 디코딩 및 재생

핵심:

HLS는 서버가 보내는 구조가 아니라 클라이언트가 가져오는 구조다 (pull-based)


3.9 이 구조가 만드는 장점과 단점

장점

  • ABR이 자연스럽게 가능
  • CDN 캐싱 활용 가능
  • 네트워크 안정성
  • 인프라 비용 절감

단점

  • polling 구조 → 지연 발생
  • segment 단위 → 즉시성 부족
  • playlist 갱신 주기에 의존

3장 한 줄 정리

HLS는 playlist라는 지도segment라는 조각으로 이루어지며, 플레이어는 그 지도를 보고 스스로 길을 찾아가는 구조다.